VPC LambdaでMomento Serverless Cacheを使う
Introduction
Momento Serverless Cacheはクラウドネイティブな
高速のサーバーレスキャッシュサービスです。
設定が簡単で管理する必要もなく、すぐに使えるのが特徴です。
Serverless cacheと名前が付いているくらいなので、
AWS Lambdaなどのサーバレス環境との親和性も高いです。
今回はAWS LambdaをVPC内にデプロイし、
そこからMomentoに対してアクセスしてみます。
Environment
- OS : MacOS 12.4
- Serverlss : 3.22.0
- Node : v18.9
- AWS CDK : 2.41.0
AWSアカウントは設定済みとします。
Create VPC with AWS CDK
まずはAWS CDKでVPC環境を作成します。
AWS CDK CLIがインストールされていない場合、このへんを参考にインストールしてください。
また、CDKでなくAWSコンソールで作成する場合はここを参考にすると良さそうです。
cdk initコマンドでテンプレートを作成して必要モジュールをインストールします。
% cdk init app --language=typescript % npm install ・ ・
次に、bin/cdk-examples.tsを少し修正。
スタック名とリージョンを適当に決め打ちします。
process.env.XXXみたいに環境変数から取得してもOKです。
#!/usr/bin/env node import 'source-map-support/register'; import * as cdk from 'aws-cdk-lib'; import { CdkExamplesStack } from '../lib/cdk-examples-stack'; const app = new cdk.App(); new CdkExamplesStack(app, 'CdkExamplesStack', { stackName: 'my-cdk-stack', env: { region: "us-east-1" }, });
CDK処理の中身であるlib/cdk-examples-stack.tsの修正をします。
ここなどを参考に
NAT GatewayつきのVPCを作成しましょう。
import * as ec2 from 'aws-cdk-lib/aws-ec2'; import * as cdk from 'aws-cdk-lib'; import { Construct } from 'constructs'; export class CdkExamplesStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); const vpc = new ec2.Vpc(this, 'my-cdk-vpc', { cidr: '10.0.0.0/16', natGateways: 1, maxAzs: 3, subnetConfiguration: [ { name: 'private-subnet-1', subnetType: ec2.SubnetType.PRIVATE_WITH_NAT, cidrMask: 24, }, { name: 'public-subnet-1', subnetType: ec2.SubnetType.PUBLIC, cidrMask: 24, }, { name: 'isolated-subnet-1', subnetType: ec2.SubnetType.PRIVATE_ISOLATED, cidrMask: 28, }, ], }); // ? update the Name tag for the VPC cdk.Aspects.of(vpc).add(new cdk.Tag('Name', 'my-cdk-vpc')); // ? update the Name tag for public subnets for (const subnet of vpc.publicSubnets) { cdk.Aspects.of(subnet).add( new cdk.Tag( 'PublicSubnet', `${vpc.node.id}-${subnet.node.id.replace(/Subnet[0-9]$/, '')}-${ subnet.availabilityZone }`, ), ); } // ? update the Name tag for private subnets for (const subnet of vpc.privateSubnets) { cdk.Aspects.of(subnet).add( new cdk.Tag( 'PrivateSubnet1', `${vpc.node.id}-${subnet.node.id.replace(/Subnet[0-9]$/, '')}-${ subnet.availabilityZone }`, ), ); } // ? update the Name tag for private subnets for (const subnet of vpc.isolatedSubnets) { cdk.Aspects.of(subnet).add( new cdk.Tag( 'PrivateSubnet2', `${vpc.node.id}-${subnet.node.id.replace(/Subnet[0-9]$/, '')}-${ subnet.availabilityZone }`, ), ); } new cdk.CfnOutput(this, 'vpcId', { value: vpc.vpcId, description: 'the ID of the VPC', }); } }
Publicサブネット1つとPrivaetサブネットを2つ作成します。
Publicサブネット(public-subnet-1)にデプロイされたリソースは
インターネットゲートウェイ経由でインターネットアクセス可能です。
また、パブリックIPを持っていればリソースにインターネットからアクセスできます。
isolated-subnet-1サブネットは、インターネットアクセス不可、
インターネットからのアクセスもできず、
同じVPCからのみ相互アクセス可能なサブネットです。
private-subnet-1サブネットが、今回使うLambda用のサブネットです。
ここにプロビジョニングされたリソースはNAT Gateway経由で
インターネットにアクセス可能ですが、インターネットからはアクセスできません。
cdk boostrapで初期化します。
このコマンドは新しい環境でデプロイするとき、最初の1回だけ実行する必要があります。
bootstrapコマンドを実行すると、CloudFormationスタックが作成され、
デプロイ時に必要なリソース郡が作成されます。
% cdk bootstrap
そしてdeployコマンド実行。
% cdk deploy
これでNAT GatewayつきのVPC環境ができ、Lambdaをデプロイする環境の準備ができました。
※料金がかかるので使い終わったら削除を忘れずに
Momentoセットアップ
Momentoを使用するには認証トークンが必要です。
ここにある記事を参考に、
認証トークンを取得しておきましょう。
このトークンはLambdaのコード内で使用します。
AWS Lambdaの実装
環境ができたので、次はLambdaを実装します。
今回はserverless frameworkを使ってLambdaを実装します。
まだインストールしていなければ、Homebrewでserverlssをインストールしておきます。
% brew install serverless % serverless --version Running "serverless" from node_modules Framework Core: 3.22.0 (local) 3.22.0 (global) Plugin: 6.2.2 SDK: 4.3.2
Lmabdaプロジェクトをcreateして必要モジュールをインストール。
% mkdirp /path/your/lambda-projects && cd /path/your/lambda-projects % serverless create --template aws-nodejs-ecma-script --name serverless-sample --path serverless-sample % cd serverless-sample/ % npm install
ここでMomento用SDKをインストールします。
% npm install --save @gomomento/sdk
serverless.ymlを↓のように修正します。
service: serverless-sample frameworkVersion: '3' plugins: - serverless-webpack provider: name: aws runtime: nodejs16.x region: us-east-1 vpc: securityGroupIds: - <default securitygroup id> subnetIds: - <private-subnet-1Subnet1のサブネットID> - <private-subnet-1Subnet2のサブネットID> functions: hello: handler: vpclambda.hello
subnetIdsに、NAT Gatewayを指定したサブネットを指定します。
そして、vpclambda.jsファイルを↓のように記述します。
import {SimpleCacheClient} from '@gomomento/sdk'; // 認証トークンを設定 const AUTH_TOKEN = "<Momento認証トークン>"; const DEFAULT_TTL = 60; // momentoクライアント初期化 const momento = new SimpleCacheClient(AUTH_TOKEN, DEFAULT_TTL); const CACHE_NAME = 'vpc_myCache'; export const hello = async (event, context, callback) => { //キャッシュリスト取得 const caches = (await momento.listCaches()).getCaches(); const names = caches.map(c => c.getName()); console.log(`cache names:${names}`); if(!names.includes(CACHE_NAME)) { // キャッシュ作成 await momento.createCache(CACHE_NAME); console.log(`${CACHE_NAME} cache created`); } // キャッシュset const setResult = await momento.set(CACHE_NAME, 'key_ts', 'value_ts'); console.log(`setResult:${setResult.text()}`); // キャッシュget const getResult = await momento.get(CACHE_NAME, 'key_ts'); console.log(`getResult:${getResult.text()}`); // キャッシュ削除 await momento.deleteCache(CACHE_NAME); console.log(`${CACHE_NAME} cache deleted`); return { statusCode: 200, body: JSON.stringify( { message: 'Hello VPC Lambda with Momento', input: event, }, null, 2 ), }; };
Momento SDKをつかってキャッシュの作成、取得、設定、削除など
ひととおりの処理を実行しています。
また、ここではトークンをコードに記述していますが、
本来ならAWS Secrets Managerとかを使ったほうがいいです。
最後にデプロイしてinvokeしてみます。
% serverless deploy ・ ・ ・ % serverless invoke -f hello Running "serverless" from node_modules { "statusCode": 200, "body": "{\n \"message\": \"Hello VPC Lambda with Momento\",\n \"input\": {}\n}" }
ちゃんと実行できてます。
CloudwatchでLambdaの実行ログをみれば、console.logの内容も確認できます。
Summary
本稿ではVPC LambdaでMomento Serverless Cacheを動かしてみました。
Momentoの初期設定やプログラムでへの追加は非常に簡単です。
Momentoについて興味がありましたら、ぜひこちらの記事もご確認ください。